
/**
 * @modulename FileFormatter
 * 
 * @description This class outputs the contents of various tables for SP2. The
 *              constructor is overloaded to handle each table.
 * 
 * @callsequence FileFormatter outputFile = new FileFormatter (outputTable);
 * 
 * @inparam Either an AssemblyListing object, an ObjectFile object, or a
 *          SymbolTable object
 * 
 * @outparam Parameters: creates an output file for the given table
 * 
 * @errorstested See JUnit test cases
 * @errorsgenerated See errata report
 * @author Travis Casper
 * @createdate 11/03/09
 * 
 * @modlog Who/When/Why
 * 
 *         Coding Standards Met: "Signed Code Leader(Jaron)"
 * 
 *         Testing Standards Met: "Signed Test Leader(Jamie)"
 */
public class FileFormatter {

	private static String newline = System.getProperty("line.separator");


	/**
	 * @modulename FileFormatter (constructor)(SymbolTable case)
	 * 
	 * @description This constructor creates an output file for an SymbolTable
	 * object
	 * 
	 * @callsequence  FileFormatter symbolTableOutput = new
	 * FileFormatter(symbolTable)
	 * 
	 * @inparam  (SymbolTable) symbolTable: this is the SymbolTable
	 * object to be output
	 * 
	 * @outparam creates an output file for an SymbolTable object
	 * 
	 * @errorstested
	 * 
	 * @errorsgenerated
	 * 
	 * @author
	 * 
	 * @createdate
	 * 
	 * @modlog Who/When/Why
	 * 
	 * Coding Standards Met: "Signed Code Leader(Jaron)"
	 * 
	 * Testing Standards Met: "Signed Test Leader(Jamie)"
	 */
	public static String formatIntermediateFile() {
		String line = new String ();
		Integer index = IntermediateFile.size() - 1;
		if (IntermediateFile.isEmptyLine) { 
			line = "Line#=" + index.toString() + "| EMPTY LINE" + newline + newline; 
		} else {
			Integer opNum = 1;
			line = "Line#=" + index.toString() + "|";

			if (IntermediateFile.lineInfo.contains("lcSet")) {
				line = line + "LC=" + Integer.toHexString(IntermediateFile.returnLocationCounter(index)) + "|";
			}

			if (IntermediateFile.lineInfo.contains("labelSet")) {
				line = line + "label=" + IntermediateFile.returnLabel(index) + "|";
			}

			line = line + "opc=" + IntermediateFile.operationArray.get(index) + "|";

			for (String opString : IntermediateFile.operandsArray.get(index)) {
				line = line + "operand" + opNum + ":" + opString +"|";
				opNum++;
			}

			if (IntermediateFile.lineInfo.contains("binOpSet")) {
				line = line + IntermediateFile.returnBinaryOperation(index);
			}

			if (IntermediateFile.lineInfo.contains("IRSet")) {
				line = line + "IR=" + IntermediateFile.returnIRBit(index) + "|";
			}

			if (IntermediateFile.lineInfo.contains("ARSet")) {
				line = line + "AR=" + IntermediateFile.returnARBit(index) + "|";
			}

			line = line + "address-flag=" + IntermediateFile.returnAddressFlags(index) + "|";

			if (IntermediateFile.debugIsOn) {
				line = line + "Debug=1" + newline;
			} else {
				line = line + "Debug=0" + newline;
			}
			line = line + "\tORIGINAL LINE: " + IntermediateFile.sourceCodeArray.get(index) + newline + newline;
		}
		return line;
	}

	/**
	 * @modulename  FileFormatter (constructor)(AssemblyListing case)
	 * 
	 * @description This constructor creates an output file for an
	 * AssemblyListing object
	 * 
	 * @callsequence  FileFormatter assemblyListingOutput = new
	 * FileFormatter(assemblyListing)
	 * 
	 * @inparam  (AssemblyListing) asseblyListing: this is the
	 * AssemblyListing object to be output
	 * 
	 * @outparam  creates an output file for an AssemblyListing object
	 * 
	 * @errorstested
	 * 
	 * @errorsgenerated
	 * 
	 * @author
	 * 
	 * @createdate
	 * 
	 * @modlog Who/When/Why
	 * 
	 * Coding Standards Met: "Signed Code Leader(Jaron)"
	 * 
	 * Testing Standards Met: "Signed Test Leader(Jamie)"
	 */
	public static String formatAssemblyListing() {
		//File errorTable = new File("src" + Main.systemPathSeparator + "ErrorTable.txt");
		//ErrorHandler errorH = new ErrorHandler(errorTable);
		String aListingString = new String();
		aListingString = "\t\t...ASSEMBLY LISTING..." + newline + newline;
		int i1 = 0;
		// set up the headers to the columns in the format we want.
		aListingString = aListingString + "LOC (HEX)";
		aListingString = aListingString + "\t";
		aListingString = aListingString + "OBJ CODE (HEX)";
		aListingString = aListingString + "\t";
		aListingString = aListingString + "B/A/R/E";
		aListingString = aListingString + "\t\t";
		aListingString = aListingString + "STMT (DEC)";
		aListingString = aListingString + "\t";
		aListingString = aListingString + "SOURCE STATEMENT";
		aListingString = aListingString + "\t" + newline;

		// add each element of each column to the table 1 column at a time, with
		// a new lone
		// after all 6 columns have been output.
		while (i1 < (AssemblyListing.size())) {
			aListingString = aListingString + Integer.toHexString(AssemblyListing.returnLocationCounter(i1));
			aListingString = aListingString + "\t\t" + AssemblyListing.returnObjectCode(i1) + "\t";
			aListingString = aListingString + "\t" + AssemblyListing.returnRelocationCode(i1) + "\t\t";
			aListingString = aListingString + (i1) + "\t\t";
			aListingString = aListingString + AssemblyListing.returnSourceCodeLine(i1) + "\t";
			aListingString = aListingString + newline;
			while (ErrorHandler.lineHasError(i1)) {
				aListingString = aListingString + "\t\t" + ErrorHandler.removeError(i1) + newline;
			}
			aListingString = aListingString + newline;
			i1++;
		}
		aListingString = aListingString + newline + newline +formatSymbolTable();
		return aListingString;
	}

	/**
	 * @modulename FileFormatter (constructor)(ObjectFile case)
	 * 
	 * @description This constructor creates an output file for an ObjectFile
	 * object
	 * 
	 * @callsequence  FileFormatter objectFileOutput = new
	 * FileFormatter(objectFile)
	 * 
	 * @inparam (ObjectFile) objectFile: this is the ObjectFile object
	 * to be output
	 * 
	 * @outparam creates an output file for an ObjectFile object
	 * 
	 * @errorstested 
	 * 
	 * @errorsgenerated 
	 * 
	 * @author
	 * 
	 * @createdate
	 * 
	 * @modlog Who/When/Why
	 * 
	 * Coding Standards Met: "Signed Code Leader(Jaron)"
	 * 
	 * Testing Standards Met: "Signed Test Leader(Jamie)"
	 */
	public static String formatObjectFile() {
		//temp variables
		int i = 0;
		String objectFileString = new String();
		//header
		objectFileString = "H|" + ObjectFile.moduleName() +"|" + ObjectFile.date()+"|";
		objectFileString = objectFileString + ObjectFile.time() +"|"+ObjectFile.programLength()+"|";
		objectFileString = objectFileString + ObjectFile.loadAddress()+"|"+ ObjectFile.numberOfLinkingRecords() +"|";
		objectFileString = objectFileString + ObjectFile.numberOfTextRecords()+"|"+ObjectFile.startAddress()+"|";
		objectFileString = objectFileString + ObjectFile.tressel()+"|"+ObjectFile.versionNumber()+"|"+ObjectFile.revisionNumber()+newline;
		//entry records
		while(i < ObjectFile.entryLength()){
			objectFileString = objectFileString +"L|"+ObjectFile.entryName(i)+"|"+ObjectFile.entryAddress(i)+"|"+ObjectFile.entryModuleName(i)+newline;
			i++;
		}
		i=0;
		//text records
		while(i<ObjectFile.textLength()){
			objectFileString = objectFileString+"T|"+ObjectFile.address(i)+"|"+ObjectFile.machineCode(i)+"|";
			if(ObjectFile.relocationS1Code(i)!=null){
				objectFileString = objectFileString+ObjectFile.relocationS1Code(i)+"|"+ObjectFile.adjustmentSignS1(i)+"|"+ObjectFile.referencedS1Symbol(i)+"|";
				if(ObjectFile.relocationS2Code(i)!=null){
					objectFileString = objectFileString+ObjectFile.relocationS2Code(i)+"|"+ObjectFile.adjustmentSignS2(i)+"|"+ObjectFile.referencedS2Symbol(i)+"|";
					if(ObjectFile.relocationS3Code(i)!=null){
						objectFileString = objectFileString+ObjectFile.relocationS3Code(i)+"|"+ObjectFile.adjustmentSignS3(i)+"|"+ObjectFile.referencedS3Symbol(i)+"|";
						if(ObjectFile.relocationS4Code(i)!=null){
							objectFileString = objectFileString+ObjectFile.relocationS4Code(i)+"|"+ObjectFile.adjustmentSignS4(i)+"|"+ObjectFile.referencedS4Symbol(i)+"|";
							if(ObjectFile.relocationS5Code(i)!=null){
								objectFileString = objectFileString+ObjectFile.relocationS5Code(i)+"|"+ObjectFile.adjustmentSignS5(i)+"|"+ObjectFile.referencedS5Symbol(i)+"|";
							}
						}
					}
				}
			}
			objectFileString=objectFileString+ObjectFile.textModuleName(i)+newline;
			i++;
		}
		//End record
		objectFileString = objectFileString +"E|"+ObjectFile.totalRecords()+"|"+ObjectFile.moduleName()+newline;
		return objectFileString;
	}

	/**
	 * @modulename FileFormatter (constructor)(SymbolTable case)
	 * 
	 * @description This constructor creates an output file for an SymbolTable
	 * object
	 * 
	 * @callsequence  FileFormatter symbolTableOutput = new
	 * FileFormatter(symbolTable)
	 * 
	 * @inparam (SymbolTable) symbolTable: this is the SymbolTable
	 * object to be output
	 * 
	 * @outparam creates an output file for an SymbolTable object
	 * 
	 * @errorstested 
	 * 
	 * @errorsgenerated 
	 * 
	 * @author
	 * 
	 * @createdate
	 * 
	 * @modlog Who/When/Why
	 * 
	 * Coding Standards Met: "Signed Code Leader(Jaron)"
	 * 
	 * Testing Standards Met: "Signed Test Leader(Jamie)"
	 */
	public static String formatSymbolTable() {
		SymbolTable.sortSymbolTable();
		String symbolTableString = new String();
		symbolTableString = "\t\t...SORTED SYMBOL TABLE..." + newline + newline;
		int i1 = -1;
		// set up the headers to the columns in the format we want.
		symbolTableString = symbolTableString + "Symbol";
		symbolTableString = symbolTableString + "\t\t\t|";
		symbolTableString = symbolTableString + "Location Address";
		symbolTableString = symbolTableString + "\t|";
		symbolTableString = symbolTableString + "Length";
		symbolTableString = symbolTableString + "\t\t\t|";
		symbolTableString = symbolTableString + "Relocation Code";
		symbolTableString = symbolTableString + "\t|";
		symbolTableString = symbolTableString + "Usage";
		symbolTableString = symbolTableString + "\t\t\t\t|";
		symbolTableString = symbolTableString + "EQU Value";
		symbolTableString = symbolTableString + "\t" + newline;

		// add each element of each column to the table 1 column at a time, with
		// a new line
		// after all 6 columns have been output.
		while (i1 < (SymbolTable.symbolArray.size() - 1)) {
			i1++;
			symbolTableString = symbolTableString + SymbolTable.symbolArray.get(i1) + "\t";
			if (SymbolTable.symbolArray.get(i1).length() < 15) {
				if (SymbolTable.symbolArray.get(i1).length() < 8) {
					symbolTableString = symbolTableString + "\t";
				}
				symbolTableString = symbolTableString + "\t";
			}
			symbolTableString = symbolTableString + "LocAdd: ";
			String locAddrString = SymbolTable.returnLocationAddress(SymbolTable.symbolArray.get(i1));
			if (locAddrString == "n/a") {
				symbolTableString = symbolTableString + locAddrString;
			} else {
				Integer locAddrInt = Integer.parseInt(locAddrString);
				symbolTableString = symbolTableString + Integer.toHexString(locAddrInt);
			}
			if (SymbolTable.locationAddressArray.get(i1).length() < 15) {
				if (SymbolTable.locationAddressArray.get(i1).length() < 8) {
					symbolTableString = symbolTableString + "\t";
				}
				symbolTableString = symbolTableString + "\t";
			}
			symbolTableString = symbolTableString + "Length: ";
			symbolTableString = symbolTableString + SymbolTable.lengthArray.get(i1);
			if (SymbolTable.lengthArray.get(i1).length() < 15) {
				if (SymbolTable.lengthArray.get(i1).length() < 8) {
					symbolTableString = symbolTableString + "\t";
				}
				symbolTableString = symbolTableString + "\t";
			}
			symbolTableString = symbolTableString + "RelCode: ";
			symbolTableString = symbolTableString + SymbolTable.relocationCodeArray.get(i1);
			if (SymbolTable.relocationCodeArray.get(i1).length() < 15) {
				if (SymbolTable.relocationCodeArray.get(i1).length() < 8) {
					symbolTableString = symbolTableString + "\t";
				}
				symbolTableString = symbolTableString + "\t";
			}
			symbolTableString = symbolTableString + "Usage: ";
			symbolTableString = symbolTableString + SymbolTable.usageArray.get(i1);
			if (SymbolTable.usageArray.get(i1).length() < 15) {
				if (SymbolTable.usageArray.get(i1).length() < 8) {
					symbolTableString = symbolTableString + "\t";
				}
				symbolTableString = symbolTableString + "\t";
			}
			symbolTableString = symbolTableString + "\tValue: ";
			symbolTableString = symbolTableString + SymbolTable.equValueArray.get(i1);
			symbolTableString = symbolTableString + newline;
		}
		return symbolTableString;

	}

	/**
	 * @modulename formatLoadMap
	 * @description Gets information from the the LoadMap Class and outputs in a table
	 * format that mirrors the one given in CRT.
	 * @callsequence 
	 * <code> FileFormatter.formatLoadMap();</code>
	 * @inparam none  
	 * @outparam none
	 * @errorstested none yet
	 * @errorsgenerated none yet
	 * @author Joseph White
	 * @createdate 11/20/09
	 * @modlog <p>
	 *         <ul>
	 *         Who/When/Why
	 *         </li> Joe 11/22/2009 Finished Initial Coding; Testing Required. 
	 *         </ul>
	 *         Coding Standards Met: "Signed Code Leader(Jaron)"
	 *         <p>
	 *         Testing Standards Met: "Signed Test Leader(Jamie)"
	 */
	public static String formatLoadMap(){
		StringBuilder loadMapString = new StringBuilder();		
		loadMapString.append("\t\t...FORMATTED LOAD MAP..." + newline + newline);
		int i1 = 0;
		// set up the headers to the columns in the format we want.
		loadMapString.append("|Symbol|");
		loadMapString.append("\t\t");
		loadMapString.append("|Type|");
		loadMapString.append("\t\t");
		loadMapString.append("|Assembler Location|");
		loadMapString.append("\t");
		loadMapString.append("|Length|");
		loadMapString.append("\t");
		loadMapString.append("|Linker Location|");
		loadMapString.append("\t");
		loadMapString.append("|Adjustment|");
		loadMapString.append("\t" + newline);

		while (i1 < (LoadMap.size())) {

			String symbol =	LoadMap.returnSymbol(i1);
			String type =LoadMap.returnType(i1);
			String assemblerLocation =LoadMap.returnAssemblerLocation(i1);
			String length =LoadMap.returnLength(i1);
			String linkerLocation =LoadMap.returnLinkerLocation(i1);
			String adjustment =LoadMap.returnAdjustment(i1);

			loadMapString.append(symbol);
			if (symbol.length() < 19) {
				loadMapString.append("\t");
				if (symbol.length() < 15) {
					if (symbol.length() < 8) {
						loadMapString.append("\t");
					}
					loadMapString.append("\t");
				}
			}

			loadMapString.append(type);
			if (type.length() < 15) {
				if (type.length() < 8) {
					loadMapString.append("\t");
				}
				loadMapString.append("\t");
			}

			loadMapString.append(assemblerLocation);
			loadMapString.append("\t\t\t");

			loadMapString.append(length);
			if (length.length() < 15) {
				if (length.length() < 8) {
					loadMapString.append("\t");
				}
				loadMapString.append("\t");
			}

			loadMapString.append(linkerLocation);
			loadMapString.append("\t\t\t");

			loadMapString.append(adjustment);
			if (adjustment.length() < 15) {
				if (adjustment.length() < 8) {
					loadMapString.append("\t");
				}
				loadMapString.append("\t");
			}
			loadMapString.append(newline);
			i1++;
		}
		return loadMapString.toString();
	}

	/**
	 * * Module Name: formatLoadFile
	 * Description:
	 * Calling Sequence
	 * 		Input Parameters
	 * 		Output Parameters
	 * Error Conditions Tested:
	 * Error Messages Generated:
	 * Original Author:
	 * Procedure Creation Date:
	 * Modification Log:
	 * 	 Who/When/Why
	 * Coding Standards Met: "Signed Code Leader(Jaron)"
	 * Testing Standards Met: "Signed Test Leader(Jamie)"
	 * @return Returns the formatted output of the LoadFile in the format of a string.
	 */
	public static String formatLoadFile(){
		String temp = new String();
		StringBuilder loadFileString = new StringBuilder();
		//		loadMapString.append("|Symbol|");
		//		loadMapString.append("\t");
		//		loadMapString.append("|Type|");
		loadFileString.append("LH|");
		loadFileString.append(LoadFile.returnModuleName());
		loadFileString.append("|padr-");
		temp = Integer.toHexString(LoadFile.returnStartAddress());
		while(temp.length()<4){
			temp = "0"+temp;
		}
		loadFileString.append(temp);
		temp = Integer.toHexString(LoadFile.returnModuleLength());
		while(temp.length()<4){
			temp = "0"+temp;
		}
		loadFileString.append("|");
		loadFileString.append(temp);
		loadFileString.append("|padr-");
		temp = Integer.toHexString(LoadFile.returnInitialLoadAddress()).toUpperCase();
		while(temp.length()<4){
			temp = "0"+temp;
		}
		loadFileString.append(temp);
		loadFileString.append("|");
		loadFileString.append(LoadFile.returnDate());
		loadFileString.append("|");
		loadFileString.append(LoadFile.returnTime());
		loadFileString.append("|");
		loadFileString.append(LoadFile.returnTressel());
		loadFileString.append("|");
		loadFileString.append(LoadFile.returnVersion());
		loadFileString.append("|");
		loadFileString.append(LoadFile.returnRevision());
		loadFileString.append(newline);

		Integer i=0;
		Integer address=0;
		while(i<LoadFile.returnNumberOfTextRecords()){
			loadFileString.append("LT|padr-");
			address= (Integer) LoadFile.returnInstructionLoadAddress(i);
			temp = Integer.toHexString(address);
			while(temp.length()<4){
				temp = "0"+temp;
			}
			loadFileString.append(temp);
			loadFileString.append("|");
			loadFileString.append(LoadFile.returnInstructionCode(address));
			loadFileString.append("|");
			loadFileString.append(LoadFile.returnInstructionModuleName(address));
			while (Linker.textErrors.lineHasError(i)) {
				loadFileString.append(newline + Linker.textErrors.removeError(i));
			}
			loadFileString.append(newline);
			i++;
		}
		loadFileString.append("LE|");
		loadFileString.append(LoadFile.returnNumberOfTextRecords());
		loadFileString.append(newline);
		return loadFileString.toString();
	}
	/**
	 * * Module Name: formatSimulatorOutput
	 * Description:
	 * Calling Sequence
	 * 		Input Parameters
	 * 		Output Parameters
	 * Error Conditions Tested:
	 * Error Messages Generated:
	 * Original Author:
	 * Procedure Creation Date:
	 * Modification Log:
	 * 	 Who/When/Why
	 * Coding Standards Met: "Signed Code Leader(Jaron)"
	 * Testing Standards Met: "Signed Test Leader(Jamie)"
	 * @return Returns the formatted output from the Simulator in the format of a string.
	 */
	public static String formatSimulatorOutput(){
		return null;
	}
}
